package controllers;

import javax.persistence.Query;

import org.apache.commons.mail.EmailException;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import models.*;
import play.Play;
import play.mvc.*;
import play.data.validation.*;

import play.db.jpa.JPA;
import service.emailManager;
import service.NotificationManager;

public class Users extends BaseController
{

    public static void register() {
        User user = new User();
		user.interests = new ArrayList<Tag>();
        renderTemplate("Users/form.html", user);
    }
    
    public static void fbregister() 
	  {		
    	    User user = new User();
    	    renderTemplate("Users/fbregister.html", user);
	  }
    
    public static void save(@Valid User user, HashMap<String, String> interests) throws Exception {
        boolean isCreate = (user.id == null);

    	if (validation.hasErrors()) {
    	    params.flash();
    	    validation.keep();
    	    register();
    	}
    	
    	if(isCreate){
    		user.badge=BadgeType.NEW_BEE;
    	}
    	
    	// for each tag the user entered;
    	if (null != interests) {
    		// badHack here!
    		user.interests = new ArrayList<Tag>();
    		user.save();
    		// /badHack
	    	for (Map.Entry<String, String> entry : interests.entrySet()) {
	    		// create a new Tag instance.
	    		Tag tag = new Tag(user, entry.getKey(), entry.getValue());
	    		
	    		// tag the offer.
	    		user.interests.add(tag);
	    	}
    	}
    	user.save();

    	if (isCreate) {
    		
    		BadgeEntity badgeEntity=new BadgeEntity();
    		badgeEntity.setUser_id(user.id);
    		Date now = new Date();
        	Timestamp cnow = new Timestamp(now.getTime());
    		badgeEntity.setNewbie(cnow.toString());
    		badgeEntity.setEmail(user.email);
    		badgeEntity.save();
    	
    		AddNewBeeBadgeNotification(user, true);
    	    success(user.id);
    	} else {
    	    ownProfile();
    	}
    }

    private static void AddNewBeeBadgeNotification(User user, boolean isCreate) throws Exception{
		NotificationManager nManager = new NotificationManager();
	    String message = "You have just earned NewBee badge.";
	    String link = Router.reverse("Users.ownprofile").toString();
		nManager.AddNewNotification(user, message, link);
    }
    
    public static void success(Long userId) throws EmailException, IOException {
        User user = User.findById(userId);
		emailManager email=new emailManager();
		email.sendEmail(user,"Bingo"," Your registration is completed. Enjoy!");
		email.sendEmail(user,"Bingo"," Congratulations! You won a Newbee Badge!");
        render(user);
    }

    public static void profile(Long userId) {
	User observedUser = User.findById(userId);
	User connectedUser = getConnectedUser();
	Boolean isOwnProfile = (observedUser == connectedUser);

	Query participatedHandshakes = JPA.em().createQuery("from " + Handshake.class.getName() + " where offererId=" + userId + " or requesterId=" + userId);
	List<Object[]> relevantHandshakeList = participatedHandshakes.getResultList();
	List<Handshake> handshakes = new ArrayList(relevantHandshakeList);

	Query openOffers = JPA.em().createQuery("from " + Offer.class.getName() + " where status='WAITING' and owner_Id=" + userId);
	List<Object[]> offerList = openOffers.getResultList();
	List<Offer> offers = new ArrayList(offerList);

	Query openRequests = JPA.em().createQuery("from " + Request.class.getName() + " where status='WAITING' and owner_Id=" + userId);
	List<Object[]> requestList = openRequests.getResultList();
	List<Request> requests = new ArrayList(requestList);

		// build a tag cloud depending on the services of
		// the user (observed user).
		
		// instantiate a new cloud instance (a wiser way is
		// to use a map instead of a list; but for compatibility
		// reasons, I'll stick on the list).
		List<TagCloudItem> tagCloud = new ArrayList<TagCloudItem>(); 
		
		// ???
		int listFlag = 0;
		
		// for each service the user has applied;
		for (ServiceHasParticipants serviceRelation : observedUser.appliedServices) {
			// for each related tag of the service;
			for (Tag tag : serviceRelation.service.tags) {
				// is tag is already found in the tag cloud?
				int tagIndex = tagCloud.indexOf(new TagCloudItem(tag.name));
				
				// if found;
				if (-1 != tagIndex) {
					// increment the count of the tag occurrence.
					((TagCloudItem) tagCloud.get(tagIndex)).count++;
				}
				
				// if not found;
				else {
					// ???
					listFlag++;
					int cssFlag = 0;
					if (listFlag % 2 == 0) {
			   	    	cssFlag = (listFlag + 2) / 2;
					} else {
						cssFlag = (listFlag + 1) / 2;
					}
					
					// create a new tag cloud item for the tag.
					TagCloudItem tagCloudItem = new TagCloudItem();
					tagCloudItem.name = tag.name;
					tagCloudItem.count = new Long(1);
					tagCloudItem.hyperlink = "/offers/search?phrase=" + tag.name;
					tagCloudItem.CssClass = "tag_" + cssFlag;
					
					// add the item to the tag cloud.
					tagCloud.add(tagCloudItem);
				}
			}
		}
		
		// instantiate a new cloud instance (a wiser way is
		// to use a map instead of a list; but for compatibility
		// reasons, I'll stick on the list).
		List<TagCloudItem> interests = new ArrayList<TagCloudItem>(); 
		
		// ???
		int listFlag2 = 0;
		
		// for each related tag of the service;
		for (Tag tag : observedUser.interests) {
			// is tag is already found in the tag cloud?
			int tagIndex = interests.indexOf(new TagCloudItem(tag.name));
			
			// if found;
			if (-1 != tagIndex) {
				// increment the count of the tag occurrence.
				((TagCloudItem) interests.get(tagIndex)).count++;
			}
			
			// if not found;
			else {
				// ???
				listFlag2++;
				int cssFlag = 0;
				if (listFlag2 % 2 == 0) {
		   	    	cssFlag = (listFlag2 + 2) / 2;
				} else {
					cssFlag = (listFlag2 + 1) / 2;
				}
				
				// create a new tag cloud item for the tag.
				TagCloudItem tagCloudItem = new TagCloudItem();
				tagCloudItem.name = tag.name;
				tagCloudItem.count = new Long(1);
				tagCloudItem.hyperlink = "/tags/search?phrase=" + tag.name;
				tagCloudItem.CssClass = "tag_" + cssFlag;
				
				// add the item to the tag cloud.
				interests.add(tagCloudItem);
			}
		}
		
		Collections.shuffle(tagCloud);
		Collections.shuffle(interests);
				
		renderArgs.put("tagUserCloud", tagCloud); 	
		renderArgs.put("interests", interests); 
		/*Tagcloud end*/
		
		BadgeManager badge = new BadgeManager();
		BadgeType badges = badge.getbadgelist();

		render(observedUser, isOwnProfile, handshakes, offers, requests,badges);
    }

    public static void ownProfile() {
	User currentUser = getConnectedUser();
	profile(currentUser.id);
    }

    public static void editProfile() {
        User connectedUser = getConnectedUser();
        User user = User.findById(connectedUser.id);
        renderTemplate("Users/form.html", user);
    }
    
    public static void setNotificationsAsRead(){
    	 User user = getConnectedUser();
    	 NotificationManager manager = new NotificationManager();
    	 manager.SetAllUserNotificationsAsRead(user);
    	 //noRender
    }
}
